﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="NewsInformationActioner.cs" company="DissingNelleman">
//   
// All rights reserved. </copyright>
// <summary>
//   The news information actioner.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace ServiceLibrary.Actioners.Activities
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    using NHibernate;

    using ServiceLibrary.Models.Base;
    using ServiceLibrary.Models.Domain;
    using ServiceLibrary.Services.Commands;
    using ServiceLibrary.Services.Queries;
    using ServiceLibrary.Services.Results;
    using NHibernate.Criterion;

    /// <summary>
    /// The news information actioner.
    /// </summary>
    public class NewsInformationActioner : ActionerBase
    {
        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="NewsInformationActioner"/> class.
        /// </summary>
        /// <param name="session">
        /// The session.
        /// </param>
        /// <param name="activeUser">
        /// The active user.
        /// </param>
        public NewsInformationActioner(ISession session, User activeUser)
            : base(session, activeUser)
        {
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The create news information.
        /// </summary>
        /// <param name="obj">
        /// The obj.
        /// </param>
        /// <returns>
        /// The <see cref="Guid"/>.
        /// </returns>
        public Guid CreateNewsInformation(NewsInformation obj)
        {
            this.Session.Save(obj);
            obj.CreatedDateTime = DateTime.Now;
            this.Log.CreateLogEntry(
                obj.ID, string.Format("Nyhedsinformation '{0}' blev oprettet.", (obj.Type != null ? obj.Type.Name : "" )), 
                Enums.LogEntryType.NewsInformation);

            return obj.ID;
        }

        /// <summary>
        /// The create news information.
        /// </summary>
        /// <param name="cmd">
        /// The cmd.
        /// </param>
        public void CreateNewsInformation(CreateNewsInformationCommand cmd)
        {
            if (cmd.Dto != null)
            {
                var obj = new NewsInformation
                              {
                                  ID = cmd.Dto.ID,
                                  ArchiveLocation = cmd.Dto.ArchiveLocation,
                                  Comments = cmd.Dto.Comments,
                                  Creator = this.Session.Get<User>(cmd.Dto.Creator),
                                  Name = cmd.Dto.Name,
                                  TimeOfActivity = cmd.Dto.TimeOfActivity,
                                  Type = this.Session.Get<NewsInformationType>(cmd.Dto.Type),
                                  IsInformationAboutFunds = cmd.Dto.IsInformationAboutFunds,
                                  IsInformationAboutProgress = cmd.Dto.IsInformationAboutProgress,
                                  IsInformationAboutResults = cmd.Dto.IsInformationAboutResults
                              };

                if (cmd.Dto.Files != null && cmd.Dto.Files.Any())
                {
                    obj.Files = this.Session.QueryOver<File>().WhereRestrictionOn(x => x.ID).IsIn(cmd.Dto.Files).List();
                }

                if (cmd.Dto.Funds != null && cmd.Dto.Funds.Any())
                {
                    obj.Funds = this.Session.QueryOver<Fund>().WhereRestrictionOn(x => x.ID).IsIn(cmd.Dto.Funds).List();
                }

                if (cmd.Dto.OwnerProjects != null && cmd.Dto.OwnerProjects.Any())
                {
                    obj.OwnerProjects = new HashSet<Project>();
                    foreach (Guid prID in cmd.Dto.OwnerProjects)
                    {
                        var project = this.Session.Get<Project>(prID);
                        if (project != null)
                        {
                            obj.OwnerProjects.Add(project);
                        }
                    }
                }

                CreateNewsInformation(obj);
            }
        }

        /// <summary>
        /// The execute search query.
        /// </summary>
        /// <param name="newsInformationQuery">
        /// The news information query.
        /// </param>
        /// <returns>
        /// The <see cref="IResult"/>.
        /// </returns>
        public IResult ExecuteSearchQuery(NewsInformationQuery newsInformationQuery)
        {
            SearchSettings settings = newsInformationQuery.Settings;
            var result = new NewsInformationResult();

            IQueryOver<NewsInformation, NewsInformation> search = this.Session.QueryOver<NewsInformation>();
            this.ApplyDefaultCriterias(newsInformationQuery.Settings, search);
            this.ApplyDefaultSearchFieldCriteriasReportsSearch(newsInformationQuery.DefaultFields, search);

            if (newsInformationQuery.WithType.HasValue && newsInformationQuery.WithType.Value != Guid.Empty)
            {
                search = search.Where(x => x.Type.ID == newsInformationQuery.WithType.Value);
            }

            if (newsInformationQuery.WithFunds != null && newsInformationQuery.WithFunds.Any())
            {
                search.RootCriteria.CreateAlias("Funds", "fs")
                          .Add(Restrictions.In("fs.ID", newsInformationQuery.WithFunds));
            }

            result.TotalRowCount = search.RowCount();
            var list = this.ApplySkipAndTake(settings, this.Sort(settings, search.List()));

            var newsInformations = list as IList<NewsInformation> ?? list.ToList();
            if (newsInformations.Any())
            {
                foreach (NewsInformation newsInformation in list)
                {
                    result.List.Add(Services.Dto.NewsInformation.Convert(newsInformation));
                }
            }

            return result;
        }

        #endregion

        #region Methods

        /// <summary>
        /// The create news information related objects.
        /// </summary>
        internal void CreateNewsInformationRelatedObjects()
        {
            IList<NewsInformationType> existingTypes = this.Session.QueryOver<NewsInformationType>().List();

            var defaultTypes = new List<string>
                                   {
                                       "Nyhedsbrev", 
                                       "Formidlings information", 
                                       "Artikler + Kronikker", 
                                       "Pressemeddelse", 
                                       "Referencer i medier", 
                                       "Publiceret informationsmateriale videoer og lign.", 
                                       "Kommunikation om strategi", 
                                       "Understøttelse, Produktlancering"
                                   };

            foreach (string type in defaultTypes)
            {
                bool alreadyExists = (from t in existingTypes where t.Name.Equals(type) select t).Any();
                if (!alreadyExists)
                {
                    var niType = new NewsInformationType { ID = Guid.NewGuid(), Name = type };
                    this.Session.Save(niType);
                }
            }
        }

        /// <summary>
        /// The delete news information.
        /// </summary>
        /// <param name="cmd">
        /// The cmd.
        /// </param>
        internal void DeleteNewsInformation(DeleteNewsInformationCommand cmd)
        {
            if (cmd.Dto != Guid.Empty)
            {
                var info = this.Session.Get<NewsInformation>(cmd.Dto);
                if (info != null)
                {
                    if (info.Files != null && info.Files.Any())
                    {
                        foreach (File f in info.Files)
                        {
                            this.Session.Delete(f);
                        }
                    }

                    this.Log.CreateLogEntry(
                        info.ID,
                        string.Format("Nyhedsinformation '{0}' blev slettet.", (info.Type != null ? info.Type.Name : "")),
                        Enums.LogEntryType.NewsInformation,
                        Enums.LogEntryActionType.Delete);
                    this.Session.Delete(info);
                }
            }
        }

        /// <summary>
        /// The update news information.
        /// </summary>
        /// <param name="cmd">
        /// The cmd.
        /// </param>
        internal void UpdateNewsInformation(UpdateNewsInformationCommand cmd)
        {
            if (cmd.Dto != null)
            {
                var obj = Session.Get<NewsInformation>(cmd.Dto.ID);
                if (obj != null)
                {
                    obj.ArchiveLocation = cmd.Dto.ArchiveLocation;
                    obj.Comments = cmd.Dto.Comments;
                    obj.Creator = this.Session.Get<User>(cmd.Dto.Creator);
                    obj.Name = cmd.Dto.Name;
                    obj.TimeOfActivity = cmd.Dto.TimeOfActivity;
                    obj.Type = this.Session.Get<NewsInformationType>(cmd.Dto.Type);
                    obj.IsInformationAboutFunds = cmd.Dto.IsInformationAboutFunds;
                    obj.IsInformationAboutProgress = cmd.Dto.IsInformationAboutProgress;
                    obj.IsInformationAboutResults = cmd.Dto.IsInformationAboutResults;

                    if (cmd.Dto.Files != null && cmd.Dto.Files.Any())
                    {
                        obj.Files.Clear();
                        obj.Files = this.Session.QueryOver<File>().WhereRestrictionOn(x => x.ID).IsIn(cmd.Dto.Files).List();
                    }

                    if (cmd.Dto.OwnerProjects != null && cmd.Dto.OwnerProjects.Any())
                    {
                        obj.OwnerProjects.Clear();
                        foreach (Guid prID in cmd.Dto.OwnerProjects)
                        {
                            var project = this.Session.Get<Project>(prID);
                            if (project != null)
                            {
                                obj.OwnerProjects.Add(project);
                            }
                        }
                    }

                    if (cmd.Dto.Funds != null && cmd.Dto.Funds.Any())
                    {
                        obj.Funds.Clear();
                        obj.Funds = this.Session.QueryOver<Fund>().WhereRestrictionOn(x => x.ID).IsIn(cmd.Dto.Funds).List();
                    }

                    this.Session.Update(obj);
                    this.Log.CreateLogEntry(
                        obj.ID,
                        string.Format("Nyhedsinformation '{0}' blev opdateret.", (obj.Type != null ? obj.Type.Name : "" )),
                        Enums.LogEntryType.NewsInformation,
                        Enums.LogEntryActionType.Update);
                }
            }
        }

        /// <summary>
        /// The sort.
        /// </summary>
        /// <param name="settings">
        /// The settings.
        /// </param>
        /// <param name="search">
        /// The search.
        /// </param>
        /// <returns>
        /// The <see cref="IOrderedEnumerable"/>.
        /// </returns>
        private IOrderedEnumerable<NewsInformation> Sort(SearchSettings settings, IList<NewsInformation> search)
        {
            bool asc = settings.SortAscending == null ? true : (bool)settings.SortAscending;

            if (settings != null && settings.OrderBy != null)
            {
                switch (settings.OrderBy)
                {
                    case "Name":
                        return asc ? search.OrderBy(x => x.Name) : search.OrderByDescending(x => x.Name);
                    case "Type":
                        return asc ? search.OrderBy(x => x.Type.Name) : search.OrderByDescending(x => x.Type.Name);

                    // Add more orderbys
                    default:
                        break;
                }
            }

            return asc ? search.OrderBy(x => x.TimeOfActivity) : search.OrderByDescending(x => x.TimeOfActivity);
        }

        #endregion

        internal void DeleteNewsInformationFile(DeleteNewsInformationFileCommand cmd)
        {
            if (cmd.OwnerNewsID.HasValue && cmd.OwnerNewsID.Value != Guid.Empty)
            {
                if (cmd.FileID.HasValue && cmd.FileID.Value != Guid.Empty)
                {
                    var newsInformation = this.Session.Get<NewsInformation>(cmd.OwnerNewsID);
                    if (newsInformation != null)
                    {
                        var fileToDelete = this.Session.Get<File>(cmd.FileID);

                        if (fileToDelete != null)
                        {
                            newsInformation.Files.Remove(fileToDelete);
                            this.Session.Update(newsInformation);

                            ServiceLibrary.Actioners.Base.FileActioner fActioner = new ServiceLibrary.Actioners.Base.FileActioner(this.Session, this.ActiveUser);
                            fActioner.DeleteFile(cmd.FileID.Value);
                        }
                    }
                }
            }
        }
    }
}